using Prism.Mvvm;
using S7.Net;
using System;
using System.Collections.ObjectModel;
using System.Timers;
using System.Threading.Tasks;

namespace MoniterPLC
{
    /// <summary>
    /// PLC服务类，负责与PLC通信并管理工位状态
    /// </summary>
    public class PLCService : BindableBase
    {
        private Plc? _plc;
        private readonly System.Timers.Timer _pollingTimer;
        private bool _isSimulationMode;
        private bool _isConnected;
        private ObservableCollection<StationModel> _stations;

        /// <summary>
        /// 连接状态改变事件
        /// </summary>
        public event EventHandler<bool>? ConnectionStatusChanged;

        /// <summary>
        /// 工位列表
        /// </summary>
        public ObservableCollection<StationModel> Stations
        {
            get { return _stations; }
            private set { SetProperty(ref _stations, value); }
        }

        /// <summary>
        /// 是否处于模拟模式
        /// </summary>
        public bool IsSimulationMode
        {
            get { return _isSimulationMode; }
            private set { SetProperty(ref _isSimulationMode, value); }
        }

        /// <summary>
        /// 是否已连接到PLC
        /// </summary>
        public bool IsConnected
        {
            get { return _isConnected; }
            private set
            { 
                if (SetProperty(ref _isConnected, value))
                { 
                    ConnectionStatusChanged?.Invoke(this, value); 
                }
            }
        }

        /// <summary>
        /// 初始化PLC服务
        /// </summary>
        public PLCService()
        {
            _stations = new ObservableCollection<StationModel>();
            _pollingTimer = new System.Timers.Timer(1000); // 1秒轮询一次
            _pollingTimer.Elapsed += OnPollingTimerElapsedAsync;
            _pollingTimer.AutoReset = true;
            InitializeStations();
        }

        /// <summary>
        /// 初始化工位列表
        /// </summary>
        public void InitializeStations()
        {
            Stations.Clear();
            // 添加示例工位
            Stations.Add(new StationModel { Name = "工位1", Address = "M100.0" });
            Stations.Add(new StationModel { Name = "工位2", Address = "M100.1" });
            Stations.Add(new StationModel { Name = "工位3", Address = "M100.2" });
            Stations.Add(new StationModel { Name = "工位4", Address = "M100.3" });
            Stations.Add(new StationModel { Name = "工位5", Address = "M100.4" });
        }

        /// <summary>
        /// 异步连接到PLC
        /// </summary>
        /// <param name="ipAddress">PLC的IP地址</param>
        /// <param name="rack">机架号</param>
        /// <param name="slot">槽号</param>
        /// <param name="cpuType">CPU类型</param>
        /// <returns>连接是否成功</returns>
        public async Task<bool> ConnectAsync(string ipAddress, int rack, int slot, CpuType cpuType)
        {
            try
            {
                // 断开现有连接
                if (_plc != null)
                {
                    await DisconnectAsync();
                }

                // 创建新的PLC连接
                _plc = new Plc(cpuType, ipAddress, (short)rack, (short)slot);
                await Task.Run(() =>
                {
                    _plc?.Open();
                });

                if (_plc?.IsConnected ?? false)
                {
                    IsConnected = true;
                    IsSimulationMode = false;
                    _pollingTimer.Start();
                    return true;
                }
                return false;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"连接错误: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 异步断开与PLC的连接
        /// </summary>
        public async Task DisconnectAsync()
        {
            try
            {
                _pollingTimer.Stop();
                if (_plc != null)
                {
                    await Task.Run(() =>
                    {
                        if (_plc.IsConnected)
                        {
                            _plc.Close();
                        }
                    });
                }
                IsConnected = false;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"断开连接错误: {ex.Message}");
            }
        }

        /// <summary>
        /// 进入模拟模式
        /// </summary>
        public void EnterSimulationMode()
        {
            // 先断开真实连接
            DisconnectAsync().Wait();
            IsSimulationMode = true;
            IsConnected = true;
            // 在模拟模式下也启动轮询
            _pollingTimer.Start();
        }

        /// <summary>
        /// 轮询定时器触发事件处理程序
        /// </summary>
        /// <param name="sender">事件发送者</param>
        /// <param name="e">事件参数</param>
        private async void OnPollingTimerElapsedAsync(object? sender, ElapsedEventArgs e)
        {
            await ReadStationsStatusAsync();
        }

        /// <summary>
        /// 异步读取工位状态
        /// </summary>
        private async Task ReadStationsStatusAsync()
        {
            if (IsSimulationMode)
            {
                // 模拟模式：随机生成工位状态
                foreach (var station in Stations)
                {
                    if (station != null)
                    {
                        Random random = new Random();
                        int statusValue = random.Next(0, 10);
                        if (statusValue < 6) // 60%概率运行中
                            station.Status = StationStatus.Running;
                        else if (statusValue < 8) // 20%概率异常
                            station.Status = StationStatus.Abnormal;
                        else // 20%概率待运行
                            station.Status = StationStatus.Waiting;
                    }
                }
            }
            else if (_plc != null && _plc.IsConnected)
            {
                // 真实模式：从PLC读取状态
                foreach (var station in Stations)
                {
                    if (station != null && !string.IsNullOrEmpty(station.Address))
                    {
                        try
                        {
                            // 尝试读取不同类型的地址
                            object? value = await Task.Run(() =>
                            {
                                return _plc?.Read(station.Address);
                            });

                            // 处理不同类型的数据
                            if (value is bool boolValue)
                            {
                                station.IsRunning = boolValue;
                            }
                            else if (value is byte byteValue)
                            {
                                station.IsRunning = byteValue > 0;
                            }
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine($"读取工位 {station.Name} 错误: {ex.Message}");
                        }
                    }
                }
            }
        }
    }
}